from rest_framework.serializers import ModelSerializer, ReadOnlyField

from company.models import Vehicle
from location.models import Location, VehicleStatus
from rest_framework import serializers
from datetime import datetime, timedelta

from location.util import GPSDistanceCalculation
from third_api.gao import GeoApi


class VehicleStatusUpdateSerializer(ModelSerializer):
    class Meta:
        model = VehicleStatus
        fields = ['status', 'latitude', 'longitude', 'speed', 'last_time']


class VehicleStatusListSerializer(ModelSerializer):
    vehicle_id = ReadOnlyField(source='vehicle.id')
    license_number = ReadOnlyField(source='vehicle.license_number')
    address = serializers.CharField(max_length=10)

    class Meta:
        model = VehicleStatus
        fields = ['vehicle_id', 'license_number', 'status', 'longitude', 'latitude', 'address', 'speed', 'last_time']

    def to_representation(self, instance):
        time = datetime.now()
        if instance.modified_on + timedelta(minutes=10) < time:
            status = 'OFFLINE'
        elif instance.modified_on + timedelta(minutes=3) > time:
            status = 'ONLINE'
        else:
            status = 'STOP'
        return {
            'vehicle_id': instance.vehicle_id,
            'license_number': instance.vehicle.license_number,
            'status': status,
            'latitude': instance.latitude,
            'longitude': instance.longitude,
            'last_time': datetime.strftime(instance.last_time, "%Y-%m-%d %H:%M:%S"),
            'speed': instance.speed if status == 'ONLINE' else 0.0,
            'address': ''
        }


class VehicleAddressSerializer(ModelSerializer):
    address = serializers.CharField(max_length=100, help_text='中文地址')
    license_number = serializers.ReadOnlyField(source='vehicle.license_number', help_text='车牌')

    class Meta:
        model = VehicleStatus
        fields = ['vehicle_id', 'last_time', 'speed', 'address', 'status', 'license_number']

    def to_representation(self, instance):
        time = datetime.now()
        if instance.modified_on + timedelta(minutes=10) < time:
            status = 'OFFLINE'
        elif instance.modified_on + timedelta(minutes=3) > time:
            status = 'ONLINE'
        else:
            status = 'STOP'
        gd = GeoApi()
        if not instance.longitude or not instance.latitude:
            address = ''
        else:
            address = gd.reverse_geotransformation(instance.longitude, instance.latitude)
        return {
            "address": address,
            "vehicle_id": instance.vehicle_id,
            "status": status,
            "last_time": datetime.strftime(instance.last_time, "%Y-%m-%d %H:%M:%S"),
            "speed": instance.speed if status == 'ONLINE' else 0.0,
            "license_number": instance.vehicle.license_number
        }


class VehicleLocationDetailSerializer(ModelSerializer):
    class Meta:
        model = Vehicle
        fields = ['id', 'license_number']

    def to_representation(self, instance):
        start_str = self.context['request'].query_params.get('start_time')
        end_str = self.context['request'].query_params.get('end_time')
        if not start_str or not end_str:
            raise serializers.ValidationError('缺少时间参数')
        start_time = datetime.strptime(start_str, "%Y-%m-%d")
        end_time = datetime.strptime(end_str, "%Y-%m-%d")

        location = Location()
        gd = GeoApi()

        # 获取mongo的gps数据
        mongo_msg = location.get_position_list(start_time, end_time, vehicle_license_number=instance.license_number)

        if len(mongo_msg) > 0:
            start_time = mongo_msg[0]['gps'][0]['occurred_time']  # 起始时间
            end_time = mongo_msg[-1]['gps'][-1]['occurred_time']  # 终止时间
            start_longitude = mongo_msg[0]['gps'][0]['longitude']  # 起始经度
            start_latitude = mongo_msg[0]['gps'][0]['latitude']  # 起始纬度
            end_longitude = mongo_msg[-1]['gps'][-1]['longitude']  # 终止经度
            end_latitude = mongo_msg[-1]['gps'][-1]['latitude']  # 终止纬度

            start_address = gd.reverse_geotransformation(start_longitude, start_latitude)  # 起始位置
            end_address = gd.reverse_geotransformation(end_longitude, end_latitude)  # 终止位置

            gps_mileage = GPSDistanceCalculation()
            total_mileage = 0
            gps = []
            cache_dict = {}  # 对上一个gps数据做缓存
            for msg in mongo_msg:
                mongo_gps = msg['gps']
                for data in mongo_gps:
                    # 过滤漂点 /
                    if not (73 <= data['longitude'] <= 135):
                        # 中国经纬度范围中国经度范围：73°33′E至135°05′E; 纬度范围：3°51′N至53°33′N
                        continue
                    gps.append([data['longitude'], data['latitude']])
                    # 对数据做缓存
                    cache_dict['previous_longitude'] = cache_dict.get('longitude')
                    cache_dict['previous_latitude'] = cache_dict.get('latitude')
                    cache_dict['longitude'] = data['longitude']
                    cache_dict['latitude'] = data['latitude']
                    # 计算每两个gps点之间的距离
                    if len(gps) < 2:
                        total_mileage = total_mileage
                    else:
                        total_mileage += gps_mileage.get_distance_hav(cache_dict['previous_longitude'],
                                                                      cache_dict['previous_latitude'],
                                                                      cache_dict['longitude'],
                                                                      cache_dict['latitude'])
        else:
            start_time = ""
            end_time = ""
            start_address = ""
            end_address = ""
            gps = []
            total_mileage = 0
        """
            Mongo Message Type,并且是按照start_timespan时间升序排序
        [
            { 
                "start_timespan" : datetime.datetime(2019, 7, 19, 9, 20, 24, 691000), 
                "gps" : [
                    {
                        "longitude" : 120.74657169265865, 
                        "latitude" : 31.80207362760237, 
                        "occurred_time" : datetime.datetime(2019, 7, 19, 9, 20, 24, 691000)
                    }
                ], 
            },
            { 
                "start_timespan" : datetime.datetime(2019, 7, 19, 9, 20, 24, 691000), 
                "gps" : [
                    {
                        "longitude" : 120.74657169265865, 
                        "latitude" : 31.80207362760237,  
                        "occurred_time" : datetime.datetime(2019, 7, 19, 9, 20, 24, 691000)
                    }
                ], 
            }
        ]
        """
        return {
            'vehicle_id': instance.id,
            'license_number': instance.license_number,
            'start_time': datetime.strftime(start_time, "%Y-%m-%d %H:%M:%S") if start_time else "",
            'end_time': datetime.strftime(end_time, "%Y-%m-%d %H:%M:%S") if end_time else "",
            'start_address': start_address,
            'end_address': end_address,
            'total_mileage': round(float(total_mileage), 3),
            'gps': gps if len(gps) < 10000 else gps[::3]
        }
